package org.study.bookmanager.service.impl;

import jakarta.annotation.Resource;
import jakarta.persistence.criteria.Predicate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;
import org.study.bookmanager.entity.*;
import org.study.bookmanager.io.reponse.RestBean;
import org.study.bookmanager.io.request.Borrow.AddBorrowReq;
import org.study.bookmanager.io.request.PageReq;
import org.study.bookmanager.repo.*;
import org.study.bookmanager.service.BorrowService;
import org.study.bookmanager.utils.DateUtils;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;


@Service
public class BorrowServiceImpl implements BorrowService {
    @Resource
    BorrowsRespository borrowsRespository;

    @Resource
    UsersRespository usersRespository;

    @Resource
    BooksRespository booksRespository;

    @Resource
    BarcodesRespsitory barcodesRespsitory;

    @Resource
    ReservationRespository reservationRespository;

    @Value("${book-manager.default.duedate}")
    int dueDate;
    /**
     * @param details
     * @param req
     * @return
     */
    @Override
    public Object addBorrow(UserDetails details, AddBorrowReq req) {
        if(!booksRespository.existsById(req.getBook_id())){
            return RestBean.Code.图书信息不存在;
        }
        Users user=usersRespository.findByuserName(details.getUsername());
        Optional<Books> book=booksRespository.findById(req.getBook_id());
        if(book.isPresent()){
            Books books=book.get();
            if(books.getAvailableToBorrow()<=0){
                return RestBean.Code.图书已借完;
            }
            books.setAvailableToBorrow(books.getAvailableToBorrow()-1);
            Barcodes barcodes=barcodesRespsitory.findByBook(books);
            barcodes.setStatus(Barcodes.Status.BORROWED_OUT);
            Borrows borrow=Borrows.builder().
                    books(books).
                    users(user).
                    borrowDate(new Date()).
                    dueDate(DateUtils.addDays(new Date(),dueDate)).build();
            barcodesRespsitory.save(barcodes);
            borrowsRespository.save(borrow);
            booksRespository.save(books);
            return borrow.getBorrowID();
        }else{
            return RestBean.Code.图书信息不存在;
        }

    }

    /**
     * @param Id
     * @return
     */
    @Override
    public Object returnBorrow(int Id) {
        if(!borrowsRespository.existsById(Id)){
            return RestBean.Code.借阅记录不存在;
        }
        Optional<Borrows> borrow=borrowsRespository.findById(Id);
        if(borrow.isPresent()){
            Borrows borrows=borrow.get();
            if(borrows.getReturnDate()!=null){
                return RestBean.Code.图书已归还;
            }
            Books books=borrows.getBooks();
            List<Reservation> reservations = reservationRespository.findByBookAndFinishFalseOrderByReservedDateAsc(books);
            if (!reservations.isEmpty()) {
                Reservation earliestReservation = reservations.get(0);
                earliestReservation.setFinish(true);
                reservationRespository.save(earliestReservation);
            }else{
                books.setAvailableToBorrow(books.getAvailableToBorrow()+1);
            }//处理一下预约
            borrows.setReturnDate(new Date());
            borrowsRespository.save(borrows);
            return RestBean.ok;
        }else{
            return RestBean.Code.服务错误;
        }
    }

    /**
     * @param details
     * @param pageReq
     * @return
     */
    @Override
    public Object getBorrows(UserDetails details, PageReq pageReq) {
        Pageable pageable = PageRequest.of(pageReq.getPage(), pageReq.getLimit());

        Specification<Borrows> specification = (root, query, criteriaBuilder) -> {
            List<Predicate> predicates = new ArrayList<>();
            Users user = usersRespository.findByuserName(details.getUsername());
            if (user != null) {
                predicates.add(criteriaBuilder.equal(root.get("users"), user));
            }
            return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
        };

        return borrowsRespository.findAll(specification, pageable);
    }

    /**
     * @param Id
     * return
     */
    @Override
    public Object getBorrow(int Id){
        if(!borrowsRespository.existsById(Id)){
            return RestBean.Code.借阅记录不存在;
        }
        Optional<Borrows> borrow=borrowsRespository.findById(Id);
        if(borrow.isPresent()){
            return borrow.get();
        }else{
            return RestBean.Code.服务错误;
        }
    }


    /**
     * @param Id
     * @return
     */
    @Override
    public Object updateBorrow(int Id) {
        if(!borrowsRespository.existsById(Id)){
            return RestBean.Code.借阅记录不存在;
        }
        Optional<Borrows> borrow=borrowsRespository.findById(Id);
        if(borrow.isPresent()){
            Borrows borrows=borrow.get();
            borrows.setDueDate(DateUtils.addDays(borrows.getDueDate(),Borrows.renewDay));
            borrowsRespository.save(borrows);
            return borrows.getBorrowID();
        }else{
            return RestBean.Code.服务错误;
        }
    }


}
